package com.szalay.desktopsearch.indexer;

import com.szalay.desktopsearch.DesktopSearchStartup;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.util.Date;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.commons.io.IOUtils;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.core.CoreContainer;
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;

/**
 *  The indexer starts the indexing task.
 * @author szalay
 */
public final class Indexer {
    /** Logger. */
    private final static Logger logger = LoggerFactory.getLogger(DesktopSearchStartup.class);
    
    //Solr core name
    private static final String CORE_NAME = "default";
    
    /** Indexer. */
    private final SolrServer solr;
    
    /** Indexing cron. */
    private final CronTrigger cron;
    
    /**
     *  Creates a new indexer.
     * @param solrDirectory the solr directory
     * @param cronExpression indexer job cron expression
     */
    public Indexer(final String solrDirectory, final String cronExpression, final String deleteCronExpression) throws ParserConfigurationException, IOException, SAXException, SchedulerException, ParseException {
        final File home = new File(solrDirectory);
        if (!home.exists()) {
            home.mkdirs();
        }
        
        final File config = new File(home, "solr.xml");
        
        //if the config file does not exist, create it
        if (!config.exists()) {
            //Copy the config file from the application resources...
            logger.info("Creating new solr.xml.");
            
            final FileOutputStream newSolrConfig = new FileOutputStream(config, false);
            final InputStream solrXmlInput = getClass().getResourceAsStream("/solr.xml");
            IOUtils.copy(solrXmlInput, newSolrConfig);
            newSolrConfig.flush();
            newSolrConfig.close();
            solrXmlInput.close();
            
            final File defaultConfig = new File(home + "/default/conf/");
            if (!defaultConfig.exists()) {
                defaultConfig.mkdirs();
            }
            
            copyFileToDirectory("/default/admin-extra.html", solrDirectory + "/default/conf/admin-extra.html");
            copyFileToDirectory("/default/elevate.xml", solrDirectory + "/default/conf/elevate.xml");
            copyFileToDirectory("/default/mapping-ISOLatin1Accent.txt", solrDirectory + "/default/conf/mapping-ISOLatin1Accent.txt");
            copyFileToDirectory("/default/schema.xml", solrDirectory + "/default/conf/schema.xml");
            copyFileToDirectory("/default/scripts.conf", solrDirectory + "/default/conf/scripts.conf");
            copyFileToDirectory("/default/solrconfig.xml", solrDirectory + "/default/conf/solrconfig.xml");
            
        }
        
        final CoreContainer container = new CoreContainer();
        container.load(solrDirectory, config);
        solr = new EmbeddedSolrServer(container, CORE_NAME);
        
        //Start task
        final Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
        scheduler.start();
        
        final JobDetail job = new JobDetail("job1", "group1", IndexingTask.class);
        job.getJobDataMap().put(SolrServer.class.getName(), solr);
        cron = new CronTrigger("trigger1", "group1", cronExpression);
        scheduler.scheduleJob(job, cron);
        logger.info("Started indexing job.");
        
        final JobDetail job2 = new JobDetail("job2", "group1", DeleteTask.class);
        job2.getJobDataMap().put(SolrServer.class.getName(), solr);
        final CronTrigger cron2 = new CronTrigger("trigger2", "group1", deleteCronExpression);
        scheduler.scheduleJob(job2, cron2);
        logger.info("Started delete job.");
    }
    
    private void copyFileToDirectory(final String fromResource, final String toPath) throws IOException {
        final InputStream input = getClass().getResourceAsStream(fromResource);
        final FileOutputStream output = new FileOutputStream(toPath, false);
        IOUtils.copy(input, output);
        output.flush();
        output.close();
        input.close();
    }
    
    /**
     *  Returns the solr server.
     * @return 
     */
    public SolrServer getSolrServer() {
        return solr;
    }
    
    /**
     * Gets the numbers of indexed documents.
     * @return
     * @throws SolrServerException 
     */
    public long getNumberOfDocumentsIndexed() throws SolrServerException {
        final SolrQuery countQuery = new SolrQuery("*:*");
        countQuery.setRows(0);
        final QueryResponse response = solr.query(countQuery);
        return response.getResults().getNumFound();
    }
    
    /**
     * Gets the next indexing time.
     * @return 
     */
    public Date getNextIndexingTime() {
        return cron.getFireTimeAfter(new Date());
    }
}
